/* *****************************************************************************
 * JFab (http://code.google.com/p/jfab)
 * Copyright (c) 2011 JFab.org
 * Admin jfab@jeffreythompson.net
 *
 * See the file "LICENSE.txt" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * *****************************************************************************/


package org.jfab.core.util;

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import javax.tools.DiagnosticCollector;
import javax.tools.JavaFileObject;


/**
 * Provides an exception thrown when trying to compile Java programs from
 * strings containing source.
 *
 * @see  <a
 *       href="http://www.ibm.com/developerworks/java/library/j-jcomp/index.html">
 *       Create dynamic applications with javax.tools</a>
 */
public class JavaStringCompilerException extends RuntimeException
{
    /** Serial version UID. */
    private static final long serialVersionUID = 1L;

    /** The fully qualified name of the class that was being compiled. */
    private Set<String> _classNames;

    /**
     * Unfortunately, Diagnostic and Collector are not Serializable, so we can't
     * serialize the collector.
     */
    private transient DiagnosticCollector<JavaFileObject> _diagnostics;

    /**
     * @param  message              Message.
     * @param  qualifiedClassNames  Qualified class names.
     * @param  diagnostics          Diagnostics.
     */
    public JavaStringCompilerException(String message,
        Set<String> qualifiedClassNames,
        DiagnosticCollector<JavaFileObject> diagnostics)
    {
        super(message);
        setClassNames(qualifiedClassNames);
        setDiagnostics(diagnostics);
    }

    /**
     * @param  qualifiedClassNames  Qualified class names.
     * @param  cause                Cause.
     * @param  diagnostics          Diagnostics.
     */
    public JavaStringCompilerException(Set<String> qualifiedClassNames,
        Throwable cause, DiagnosticCollector<JavaFileObject> diagnostics)
    {
        super(cause);
        setClassNames(qualifiedClassNames);
        setDiagnostics(diagnostics);
    }

    /**
     * @param  message              Message.
     * @param  qualifiedClassNames  Qualified class names.
     * @param  cause                Cause.
     * @param  diagnostics          Diagnostics.
     */
    public JavaStringCompilerException(String message,
        Set<String> qualifiedClassNames, Throwable cause,
        DiagnosticCollector<JavaFileObject> diagnostics)
    {
        super(message, cause);
        setClassNames(qualifiedClassNames);
        setDiagnostics(diagnostics);
    }

    /**
     * @return  the names of the classes whose compilation caused the compile
     *          exception.
     */
    public Collection<String> getClassNames()
    {
        return Collections.unmodifiableSet(_classNames);
    }

    /**
     * Gets the diagnostics collected by this exception.
     *
     * @return  this exception's diagnostics.
     */
    public DiagnosticCollector<JavaFileObject> getDiagnostics()
    {
        return _diagnostics;
    }

    /**
     * @param  qualifiedClassNames  Qualified class names.
     */
    private void setClassNames(Set<String> qualifiedClassNames)
    {
        // Create a new HashSet because the set passed in may not
        // be Serializable. For example, Map.keySet() returns a non-Serializable
        // set.
        _classNames = new HashSet<String>(qualifiedClassNames);
    }

    /**
     * @param  diagnostics  Diagnostics.
     */
    private void setDiagnostics(DiagnosticCollector<JavaFileObject> diagnostics)
    {
        _diagnostics = diagnostics;
    }
}
